package chances.epg.commons.utils;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class RegionUtils {
	final static MessageFormat format = new MessageFormat(
			"left:{0}px;top:{1}px;width:{2}px;height:{3}px;");
	final static MessageFormat rectFormat = new MessageFormat("{0},{1},{2},{3}");

	public static class Dimen implements Serializable {
		private static final long serialVersionUID = 6399274992701579372L;
		public int width;
		public int height;

		public int getWidth() {
			return this.width;
		}

		public void setWidth(int width) {
			this.width = width;
		}

		public int getHeight() {
			return this.height;
		}

		public void setHeight(int height) {
			this.height = height;
		}
		public String toString() {
				return	"width:"+this.width + "px; height"+ this.height + "px" ;
		}
		public Dimen(int width, int height) {
			this.width = width;
			this.height = height;
		}
	}

	public static class Region extends Dimen {

		private static final long serialVersionUID = 1L;
		public int top;
		public int left;

		public Region(int left, int top, int width, int height) {
			super(width, height);
			this.left = left;
			this.top = top;
		}

		public String getStyle() {
			return toString();
		}

		public Region(int width, int height) {
			super(width, height);
		}

		public Region(Dimen cell) {
			super(cell.width, cell.height);
		}

		public String getRect() {
			return rectFormat.format(new Object[] { "" + this.left,
					"" + this.top, "" + this.width, "" + this.height });
		}

		public int getTop() {
			return this.top;
		}

		public void setTop(int top) {
			this.top = top;
		}

		public int getLeft() {
			return this.left;
		}

		public void setLeft(int left) {
			this.left = left;
		}

		public void setLocation(int x, int y) {
			this.left = x;
			this.top = y;
		}

		public String toString() {
			return format.format(new Object[] { this.left + "", this.top + "",
					this.width + "", this.height + "" });
		}

		public void add(Region region) {
			this.width += region.width;
			this.height += region.height;
			this.top += region.top;
			this.height += region.height;
		}

		public Region clone() {
			Region result = new Region(this.left, this.top, this.width,
					this.height);
			return result;

		}

		public void setSize(int width, int height) {
			this.width = width;
			this.height = height;
		}

		public void move(int left2, int top2) {
			this.left += left2;
			this.top += top2;
		}

	}

	/**
	 * 生成水平居中的坐�?
	 * 
	 * @param xywh
	 *            "left,top,width,height"
	 * @param wh
	 *            "width,height"
	 * @return
	 */
	public static Region center(String xywh, String wh) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int left = aRegion.getLeft() + (aRegion.getWidth() - aDime.getWidth())
				/ 2;
		return new Region(left, aRegion.top, aDime.getWidth(),
				aDime.getHeight());
	}

	/**
	 * 生成水平多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static Region[] centerList(String xywh, String wh, int size,
			int space) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int allWidth = aDime.getWidth() * size + space * (size - 1);

		Region[] result = new Region[size];
		if (aRegion.getWidth() >= allWidth) {
			int aTop = aRegion.getTop() + (aRegion.height - aDime.height) / 2;
			int left = aRegion.getLeft() + (aRegion.getWidth() - allWidth) / 2;

			for (int i = 0; i < size; i++) {
				result[i] = new Region(left + i * (space + aDime.getWidth()),
						aTop, aDime.getWidth(), aDime.getHeight());
			}
			return result;
		} else {
			throw new RuntimeException(xywh + "<" + wh);
		}
	}

	/**
	 * 生成垂直多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static Region[] middleList(String xywh, String wh, int size,
			int space) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int allHeight = aDime.getHeight() * size + space * (size - 1);
		Region[] result = new Region[size];
		if (aRegion.getHeight() >= allHeight) {
			int aLeft = aRegion.left + (aRegion.width - aDime.width) / 2;
			int top = aRegion.getTop() + (aRegion.getHeight() - allHeight) / 2;
			for (int i = 0; i < size; i++) {
				result[i] = new Region(aLeft, top + i
						* (space + aDime.getHeight()), aDime.getWidth(),
						aDime.getHeight());
			}
			return result;
		} else {
			throw new RuntimeException(xywh + "<" + wh);
		}
	}

	/**
	 * 生成垂直多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static Region middle(String xywh, String wh) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);

		int top = aRegion.getTop() + (aRegion.getHeight() - aDime.getHeight())
				/ 2;
		return new Region(aRegion.left, top, aDime.getWidth(),
				aDime.getHeight());
	}

	/**
	 * 生成垂直多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static Region centerMiddle(String xywh, String wh) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int left = aRegion.getLeft() + (aRegion.getWidth() - aDime.getWidth())
				/ 2;
		int top = aRegion.getTop() + (aRegion.getHeight() - aDime.getHeight())
				/ 2;
		return new Region(left, top, aDime.getWidth(), aDime.getHeight());
	}

	/**
	 * 生成垂直多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static List<Region> centerMiddleList(String xywh, String wh,
			int row, int col) {
		List<Region> result = new ArrayList<Region>();
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int left = aRegion.getLeft() + (aRegion.getWidth() - aDime.getWidth())
				/ 2;
		int top = aRegion.getTop() + (aRegion.getHeight() - aDime.getHeight())
				/ 2;
		Region[] res = getGridRect(row, col, aDime);
		for (Region region : res) {
			region.move(left, top);
			result.add(region);
		}
		return result;

	}

	/**
	 * 生成垂直多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @return
	 */
	public static Region right(String xywh, String wh) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int allWidth = aRegion.width - aDime.width;
		aRegion.left = aRegion.left + allWidth;
		aRegion.width = aDime.width;
		aRegion.height = aDime.height;
		return aRegion;
	}

	/**
	 * 生成垂直多个居中位置
	 * 
	 * @param xywh
	 * @param wh
	 * @return
	 */
	public static Region rightMiddle(String xywh, String wh) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int allWidth = aRegion.width - aDime.width;
		aRegion.left = aRegion.left + allWidth;
		aRegion.top = (aRegion.height - aDime.height) / 2 + aRegion.top;
		aRegion.width = aDime.width;
		aRegion.height = aDime.height;
		return aRegion;
	}

	/**
	 * 生成水平居右中位�?
	 * 
	 * @param xywh
	 * @param wh
	 * @return
	 */
	public static Region[] rightCols(String zone, String wh, int max, int space) {
		Dimen aAllDime = parseDimen(zone);
		Dimen aDime = parseDimen(wh);
		int row = aAllDime.width / aDime.width;
		if (row <= 0) {
			return new Region[0];
		}
		if (row >= max && max != -1) {
			row = max;
		}
		Region[] result = new Region[row];
		int left = aAllDime.width;
		for (int i = 0; i < row; i++) {
			left = aAllDime.width - ((i + 1) * aDime.width) - (i * space);
			result[i] = new Region(left, 0, aDime.width, aDime.height);
		}
		return result;
	}

	public static Region[] rightRows(String zone, String wh, int max, int space) {
		Dimen aAllDime = parseDimen(zone);
		Dimen aDime = parseDimen(wh);
		int row = aAllDime.height / aDime.height;
		if (row <= 0) {
			return new Region[0];
		}
		if (row >= max && max != -1) {
			row = max;
		}
		Region[] result = new Region[row];
		int left = aAllDime.height;
		for (int i = 0; i < row; i++) {
			left = aAllDime.height - ((i + 1) * aDime.height) - (i * space);
			result[i] = new Region(left, 0, aDime.width, aDime.height);
		}
		return result;
	}

	/**
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static Region[] rightList(String xywh, String wh, int size, int space) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int allheight = aDime.height * size + space * (size - 1);

		Region[] result = new Region[size];
		if (aRegion.height >= allheight) {
			int allWidth = aRegion.width - aDime.width;
			int left = aRegion.left + allWidth;
			int aTop = aRegion.top + (aRegion.height - allheight) / 2;

			for (int i = 0; i < size; i++) {
				result[i] = new Region(left, aTop + (space + aDime.getHeight())
						* i, aDime.getWidth(), aDime.getHeight());
			}
			return result;
		} else {
			throw new RuntimeException(xywh + "<" + wh);
		}
	}

	/**
	 * 生成靠底�?
	 * 
	 * @param xywh
	 * @param wh
	 * @return
	 */

	public static Region bottom(String xywh, String wh) {

		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int top = aRegion.height - aDime.height;
		aRegion.top = aRegion.top + top;
		aRegion.width = aDime.width;
		aRegion.height = aDime.height;
		return aRegion;
	}

	/**
	 * 
	 * @param xywh
	 * @param wh
	 * @param size
	 * @param space
	 * @return
	 */
	public static Region[] bottomCols(String xywh, String wh, int size,
			int space) {
		Region aRegion = parseRect(xywh);
		Dimen aDime = parseDimen(wh);
		int allWidth = aDime.getWidth() * size + space * (size - 1);
		Region[] result = new Region[size];
		if (aRegion.getWidth() >= allWidth) {
			int aLeft = aRegion.left + (aRegion.width - allWidth) / 2;
			int top = aRegion.getTop()
					+ (aRegion.getHeight() - aDime.getHeight());
			for (int i = 0; i < size; i++) {
				result[i] = new Region(aLeft + i * (space + aDime.getWidth()),
						top, aDime.getWidth(), aDime.getHeight());
			}
			return result;
		} else {
			throw new RuntimeException(xywh + "<" + wh);
		}
	}

	public static Region parseRect(String str) {
		String[] xywh = str.split(",");
		return new Region(Integer.parseInt(xywh[0]), Integer.parseInt(xywh[1]),
				Integer.parseInt(xywh[2]), Integer.parseInt(xywh[3]));
	}

	public static Dimen parseDimen(String str) {
		String[] xywh = str.split(",");
		return new Dimen(Integer.parseInt(xywh[0]), Integer.parseInt(xywh[1]));
	}

	public static Region[] getTilesRect(String cell, String posStr,
			int rowspace, int colspace) {
		Dimen aDime = parseDimen(cell);
		return getTilesRect(aDime, posStr, rowspace, colspace);

	}

	/**
	 * 缩放
	 * 
	 * @param obj
	 * @param width
	 * @param height
	 * @return
	 */
	public static Region zoom(Object obj, float pre) {
		Region aRegion = toRegion(obj);

		int width = (int) (aRegion.getWidth() * pre);
		int height = (int) (aRegion.getHeight() * pre);
		int left = (aRegion.getWidth() - width) / 2;
		int top = (aRegion.getHeight() - height) / 2;
		aRegion.setSize(width, height);
		aRegion.move(left, top);
		return aRegion;
	}

	/**
	 * 移动坐标
	 * 
	 * @param obj
	 * @param left
	 * @param top
	 * @return
	 */
	public static Region move(Object obj, int left, int top) {
		Region aRegion = toRegion(obj);
		aRegion.move(left, top);
		return aRegion;
	}

	private static Region toRegion(Object obj) {
		Region region = null;
		if (obj instanceof Region) {
			region = (Region) obj;
			region = region.clone();
		} else {

			region = parseRect(obj.toString());
		}
		return region;
	}

	public static Region[] getTilesRect(Dimen cell, String posStr,
			int rowspace, int colspace) {
		StringTokenizer token = new StringTokenizer(posStr, ",:");
		int col = 0;
		int row = 0;
		while (token.hasMoreElements()) {
			String str = (String) token.nextElement();
			int aCol = str.charAt(0) - 'A' + 1;
			int aRow = Integer.parseInt(str.substring(1));
			col = aCol > col ? aCol : col;
			row = aRow > row ? aRow : row;
		}
		Region[][] cellRects = getGridRect(row, col, cell, rowspace, colspace);
		String[] cells = posStr.split(",");
		Region[] result = new Region[cells.length];
		for (int i = 0; i < cells.length; i++) {
			String cellStr = cells[i];
			if (cellStr.indexOf(":") > 0) {
				String[] colrow = cellStr.split(":");
				int beginX = colrow[0].charAt(0) - 'A';
				String strBeginY = colrow[0].substring(1);
				int beginY = Integer.parseInt(strBeginY) - 1;

				int endX = colrow[1].charAt(0) - 'A';
				String strEndY = colrow[1].substring(1);
				int endY = Integer.parseInt(strEndY) - 1;

				int numX = endX - beginX + 1;
				int numY = endY - beginY + 1;

				int height = numY * cell.height + (numY - 1) * rowspace;
				int width = numX * cell.width + (numX - 1) * colspace;
				int x = cellRects[beginY][beginX].left;
				int y = cellRects[beginY][beginX].top;
				result[i] = new Region(x, y, width, height);
			} else {
				int x = cellStr.charAt(0) - 'A';
				int y = Integer.parseInt(cellStr.substring(1)) - 1;
				result[i] = cellRects[y][x];
			}
		}
		return result;
	}

	public static Region[] getGridRect(int row, int col, String cell,
			int rowspace, int colspace) {
		Dimen aDime = parseDimen(cell);
		Region[][] rects = getGridRect(row, col, aDime, rowspace, colspace);
		ArrayList<Region> result = new ArrayList<Region>();
		for (int i = 0; i < rects.length; i++) {
			for (int j = 0; j < rects[i].length; j++) {
				result.add(rects[i][j]);
			}
		}
		return result.toArray(new Region[result.size()]);
	}

	public static Region[][] getGridRect(int row, int col, Dimen cell,
			int rowspace, int colspace) {
		Region[][] result = new Region[row][col];
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				int x = (cell.getWidth() + colspace) * j;
				int y = (cell.getHeight() + rowspace) * i;
				Region aRect = new Region(cell);
				aRect.setLocation(x, y);
				result[i][j] = aRect;
			}
		}
		return result;
	}

	public static Region[] getGridRect(int row, int col, String cell) {
		Dimen region = parseDimen(cell);
		return getGridRect(row, col, region);
	}

	public static Region[] getGridRect(int row, int col, Dimen region) {
		int rowCount = region.getHeight() / row;
		int colCount = region.getWidth() / col;
		return getGridRect(row, col, colCount + "," + rowCount, 0, 0);
	}

	public static Region[] flowCols(String region, String widths, int height,
			int space) {
		Region aRect = parseRect(region);
		String[] values = widths.split(",");
		Region[] result = new Region[values.length];
		int left = aRect.left;
		for (int i = 0; i < values.length; i++) {
			int width = Integer.parseInt(values[i]);
			result[i] = new Region(width, height);
			result[i].top = aRect.top;
			result[i].left = left;
			left = left + space + width;
		}

		return result;
	}

	public static String toStr(Object obj) {
		return ToStringBuilder.reflectionToString(obj, ToStringStyle.MULTI_LINE_STYLE);
	}
}
